package pikasial.images;

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;

/**
 * Cette classe représente un album photos.
 * <p>
 * Un album photos est une liste d'images
 * portant un nom, et dont la vue est un <code>OngletPhotos</code>.
 * L'album par défaut est un album particulier, puisqu'il concerne
 * l'affichage des photos sans prendre en compte les albums (par
 * exemple pour afficher les photos contenues dans un dossier, on les
 * place dans l'album par défaut).
 *
 * @author ESIAL - Groupe 14
 */
public final class AlbumPhotos extends java.util.Observable implements ImageContainer {

    /** Le nom de l'album. */
    private String name;

    private Date dateCreation;
    /** Stocke les images **/
    private List<PikImage> images;

    /**
     * Crée un album portant le nom spécifié en argument, et contenant
     * tous les élements de la collection d'images spécifiée.
     *
     * @param nom - le nom de l'album
     * @param collec - la collection d'images Ã  ajouter
     */
    public AlbumPhotos(final String nom) {
    	this(nom,java.util.Calendar.getInstance().getTime());
    }

    public AlbumPhotos(final String nom, final Date creation) {
    	name = nom;
        dateCreation = creation;
        images = Collections.synchronizedList(new ArrayList<PikImage>());
    }

    /**
     * Ajoute toutes les images spécifiées à la collection.
     * <p>
     * L'opération se fait dans un nouveau Thread, car la création
     * des vignettes est une opération longue.
     * @param imgs - les images à ajouter
     * @see pikasial.images.ImageContainer#addAllImages(java.util.Collection)
     */
    public void addAllImages(final Collection<PikImage> imgs) {
        if (!imgs.isEmpty()) {
            images.addAll(imgs);
        }
        setChanged();
        notifyObservers(null);
    }

    /**
     * Ajoute l'image spécifiée à la collection.
     * <p>
     * L'ajout de l'image dans la liste se fait dans l'Event-Dispatching Thread
     *
     * @param image - l'image à ajouter
     * @see pikasial.images.ImageContainer#addImage(pikasial.images.PikImage)
     */
    public void addImage(final PikImage image) {
        images.add(image);
        setChanged();
        notifyObservers(null);
    }

    /**
     * Retourne la date de création de l'album.
     *
     * @return la date de création de l'album
     * @see pikasial.images.metadata.MetadataContainer#getCreationDate()
     */
    public Date getDateCreation() {
        return dateCreation;
    }

    /**
     * Permet d'accèder à l'image d'indice spécifié dans la liste.
     *
     * @param index - l'indice de l'image à retourner
     * @return l'image contenue à l'indice index, ou null si l'indice
     * est erroné
     * @see pikasial.images.ImageContainer#getImage(int)
     */
    public PikImage getImage(final int index) {
        return images.get(index);
    }

    /**
     * Retourne le nombre d'images contenues dans la liste d'images.
     *
     * @return le nombre d'images dans cet album
     * @see pikasial.images.ImageContainer#getImageCount()
     */
    public int getImageCount() {
        return images.size();
    }

    /**
     * Retourne les images contenues entre les indices spécifiés.
     *
     * @param indA - l'indice de la première image inclue
     * @param indB - l'indice de la première image exclue
     * @return la collection des images contenues entre les 2 indices,
     * ou null si les indices sont erronés
     * @see pikasial.images.ImageContainer#getImageRange(int, int)
     */
    public Collection<PikImage> getImageRange(final int indA, final int indB) {
        if (indA > indB) {
            throw new IllegalArgumentException("Le premier paramètre indA doit " +
                "être inférieur au deuxième !");
        }
        Collection<PikImage> collec = new ArrayList<PikImage>();
        int i = 0;
        boolean dansInterv = false;
        for (PikImage pik : images) {
            if (i == indA) {
                dansInterv = true;
            }
            if (dansInterv) {
                collec.add(pik);
            }
            if (i++ == indB) {
                break;
            }
        }
        return collec;
    }

    /**
     * Retourne le nom de l'album représenté par l'instance courante.
     *
     * @return le nom de l'album
     * @see pikasial.images.metadata.MetadataContainer#getName().
     */
    public String getName() {
        return name;
    }

    /**
     * Supprime toutes les images.
     * <p>
     * Utiliser un nouveau modèle est beaucoup plus efficace
     * que vider le modèle courant, mais il faut avertir l'observateur
     * (l'OngletPhotos, qui a la JList basée sur ce modèle) du
     * changement.
     *
     * @see pikasial.images.ImageContainer#removeAll()
     */
    public void removeAll() {
        images.clear();
        setChanged();
        notifyObservers(null);
    }

    /**
     * Supprime l'image d'indice spécifié.
     *
     * @param index - l'indice de l'image à supprimer
     * @see pikasial.images.ImageContainer#removeImage(int)
     */
    public void removeImage(final int index) {
        images.remove(index);
        setChanged();
        notifyObservers(null);
    }

    public void removeImage(PikImage pik) {
    	images.remove(pik);
    	setChanged();
        notifyObservers(null);
	}

    /**
     * Retourne la représentation de cet album sous forme de chaîne de
     * caractères.
     *
     * @return le nom de l'album
     * @see java.lang.Object#toString()
     */
    public String toString() {
        return getName() + " "+getImageCount();
    }

    public Collection<PikImage> getAllImages() {
        return images;
    }

    public boolean isEmpty() {
        return images.isEmpty();
    }

    public void removeRange(int ind1, int ind2) {
        if (ind1 > ind2) {
            throw new IllegalArgumentException("Le premier paramètre ind1 doit " +
                "être inférieur au deuxième !");
        }
        Iterator<PikImage> iter = images.iterator();
        boolean dansInterv = false;
        int i = 0;
        while (iter.hasNext()) {
            iter.next();
            if (i == ind1) {
                dansInterv = true;
            }
            if (dansInterv) {
                iter.remove();
            }
            if (i++ == ind2) {
                break;
            }
        }
        setChanged();
        notifyObservers(null);
    }

	public boolean containsImage(PikImage pik) {
		return images.contains(pik);
	}

	public boolean containsImage(String name) {
		boolean trouve = false;
		for (PikImage pik : images) {
			if (pik.getName().equals(name)) {
				trouve = true;
				break;
			}
		}
		return trouve;
	}

}
